package com.cskaoyan.wordmemorize.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.EmployeeConverter;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeDO;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeRoleDO;
import com.cskaoyan.wordmemorize.dao.entity.PermissionDO;
import com.cskaoyan.wordmemorize.dao.entity.RolePermissionDO;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeMapper;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeRoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.PermissionMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RolePermissionMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteEmployeeRoleOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.EmployeeDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.request.EmployeeCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class EmployeeServiceImpl implements EmployeeService {


    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    EmployeeConverter employeeConverter;

    @Autowired
    EmployeeRoleMapper employeeRoleMapper;

    @Autowired
    RolePermissionMapper rolePermissionMapper;

    @Autowired
    PermissionMapper permissionMapper;


    /**
     * 后台登录接口
     * @param userName
     * @param password
     * @return
     */
    @Override
    public EmployeeDTO login(String userName, String password) {

        // 1. 将明文密码变为密文密码
        String encodePassword = SaSecureUtil.md5(password);

        // 2. 根据用户名和密码查询数据库
        LambdaQueryWrapper<EmployeeDO> employeeWrapper = new LambdaQueryWrapper<>();
        employeeWrapper.eq(EmployeeDO::getName, userName)
                .eq(EmployeeDO::getPassword, encodePassword);

        EmployeeDO employeeDO = employeeMapper.selectOne(employeeWrapper);
        if (employeeDO == null) {
            throw new BusinessException(ResultCodeEnum.LOCAL_LOGIN_FAIL);
        }



        return employeeConverter.employeeDO2DTO(employeeDO);
    }

    /**
     * 获取当前后台员工信息(登录之后请求，其中包含员工的权限集合)
     * @param employeeId
     * @return
     */
    @Override
    public EmployeeDTO getEmployeeInfo(Long employeeId) {


        EmployeeDO employeeInfo = employeeMapper.getEmployeeInfo(employeeId);
        return employeeConverter.employeeDO2DTO(employeeInfo);
    }

    /**
     * 分页查询员工信息(后台账号权限管理-员工管理)
     * @param request
     * @return
     */
    @Override
    public PageDTO<EmployeeDTO> getEmployeePage(PageRequest request) {
        List<EmployeeDO> employeeList;
        long total;
        LambdaQueryWrapper<EmployeeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EmployeeDO::getIsDeleted, 0);
        // 判断是否分页
        if (request.getPageNum() == null || request.getCount() == null) {
            // 全查
            employeeList = employeeMapper.selectList(wrapper);
            total = employeeList.size();
        } else {
            // 分页查
            Page<EmployeeDO> page = new Page<>(request.getPageNum(), request.getCount());
            Page<EmployeeDO> employeePage = employeeMapper.selectPage(page, wrapper);
            employeeList = employeePage.getRecords();
            total = employeePage.getTotal();
        }
        // 为每个员工填充 roleIds 和 perms
        if (employeeList != null) {
            for (EmployeeDO employeeDO : employeeList) {
                List<EmployeeRoleDO> roleList = employeeRoleMapper.selectList(
                        new LambdaQueryWrapper<EmployeeRoleDO>()
                                .eq(EmployeeRoleDO::getEmployeeId, employeeDO.getId()));
                List<Long> roleIds = roleList.stream()
                        .map(EmployeeRoleDO::getRoleId)
                        .collect(Collectors.toList());
                // 查询所有角色对应的权限id
                List<Long> permissionIds = new ArrayList<>();
                if (!roleIds.isEmpty()) {
                    LambdaQueryWrapper<RolePermissionDO> rpWrapper = new LambdaQueryWrapper<>();
                    rpWrapper.in(RolePermissionDO::getRoleId, roleIds);
                    List<RolePermissionDO> rolePermissionList = rolePermissionMapper.selectList(rpWrapper);
                    permissionIds = rolePermissionList.stream()
                            .map(RolePermissionDO::getPermissionId)
                            .distinct()
                            .collect(Collectors.toList());
                }
                // 查询所有权限码
                List<String> perms = new ArrayList<>();
                if (!permissionIds.isEmpty()) {
                    LambdaQueryWrapper<PermissionDO> permWrapper = new LambdaQueryWrapper<>();
                    permWrapper.in(PermissionDO::getId, permissionIds);
                    List<PermissionDO> permissionList = permissionMapper.selectList(permWrapper);
                    perms = permissionList.stream()
                            .map(PermissionDO::getPermissionCode)
                            .filter(Objects::nonNull)
                            .distinct()
                            .collect(Collectors.toList());
                }
                employeeDO.setRoleIds(roleIds);
                employeeDO.setPerms(perms);
            }
        }
        // 转换为 PageDTO
        return employeeConverter.emoloyeePage2PageDTO(employeeList, total);
    }

    /**
     * 添加员工信息(后台账号权限管理-员工管理)
     * @param command
     */
    @Override
    @OperateLog(dataType = "员工", operateType = 1, description = "添加员工信息")
    public void addEmployee(EmployeeCommand command) {
        // 1. 校验用户名唯一
        LambdaQueryWrapper<EmployeeDO> nameWrapper = new LambdaQueryWrapper<>();
        nameWrapper.eq(EmployeeDO::getName, command.getName());
        if (employeeMapper.selectCount(nameWrapper) > 0) {
            throw new BusinessException("用户名已存在", ResultCodeEnum.FAIL.getCode());
        }
        // 2. 校验手机号唯一
        LambdaQueryWrapper<EmployeeDO> phoneWrapper = new LambdaQueryWrapper<>();
        phoneWrapper.eq(EmployeeDO::getPhoneNumber, command.getPhoneNumber());
        if (employeeMapper.selectCount(phoneWrapper) > 0) {
            throw new BusinessException("手机号已存在", ResultCodeEnum.FAIL.getCode());
        }
        // 3. 密码加密
        command.setPassword(SaSecureUtil.md5(command.getPassword()));
        // 4. 转换并设置isDeleted=0
        EmployeeDO employeeDO = employeeConverter.command2EmployeeDO(command);
        employeeDO.setIsDeleted(0);
        employeeMapper.insert(employeeDO);
        // 5. 插入所有角色
        if (command.getRoleIds() != null && !command.getRoleIds().isEmpty()) {
            for (String roleIdStr : command.getRoleIds()) {
                EmployeeRoleDO rel = new EmployeeRoleDO();
                rel.setEmployeeId(employeeDO.getId());
                rel.setRoleId(Long.valueOf(roleIdStr));
                rel.setIsDeleted(0);
                employeeRoleMapper.insert(rel);
            }
        }
    }

    /**
     * 更新员工信息(后台账号权限管理-员工管理)
     * @param command
     */
    @Override
    @OperateLog(dataType = "员工", operateType = 4, description = "更新员工信息")
    public void updateEmployee(EmployeeCommand command) {
        if (command.getId() == null) {
            throw new BusinessException("员工ID不能为空", ResultCodeEnum.FAIL.getCode());
        }
        Long empId = Long.valueOf(command.getId());
        // 1. 校验用户名唯一（排除自己）
        LambdaQueryWrapper<EmployeeDO> nameWrapper = new LambdaQueryWrapper<>();
        nameWrapper.eq(EmployeeDO::getName, command.getName()).ne(EmployeeDO::getId, empId);
        if (employeeMapper.selectCount(nameWrapper) > 0) {
            throw new BusinessException("用户名已存在", ResultCodeEnum.FAIL.getCode());
        }
        // 2. 校验手机号唯一（排除自己）
        LambdaQueryWrapper<EmployeeDO> phoneWrapper = new LambdaQueryWrapper<>();
        phoneWrapper.eq(EmployeeDO::getPhoneNumber, command.getPhoneNumber()).ne(EmployeeDO::getId, empId);
        if (employeeMapper.selectCount(phoneWrapper) > 0) {
            throw new BusinessException("手机号已存在", ResultCodeEnum.FAIL.getCode());
        }
        // 3. 密码加密（如有修改）
        EmployeeDO old = employeeMapper.selectById(empId);
        if (command.getPassword() != null && !command.getPassword().isEmpty()
                && !SaSecureUtil.md5(command.getPassword()).equals(old.getPassword())) {
            command.setPassword(SaSecureUtil.md5(command.getPassword()));
        } else {
            command.setPassword(old.getPassword());
        }
        // 4. 转换并设置isDeleted=0
        EmployeeDO employeeDO = employeeConverter.command2EmployeeDO(command);
        employeeDO.setIsDeleted(0);
        employeeMapper.updateById(employeeDO);
        // 5. 只处理新增角色
        List<Long> dbRoleIds = employeeRoleMapper.selectList(
                        new LambdaQueryWrapper<EmployeeRoleDO>().eq(EmployeeRoleDO::getEmployeeId, empId)).stream()
                .map(EmployeeRoleDO::getRoleId).collect(Collectors.toList());
        Set<Long> newRoleIds = command.getRoleIds() == null ? new HashSet<>()
                : command.getRoleIds().stream().map(Long::valueOf).collect(Collectors.toSet());
        for (Long roleId : newRoleIds) {
            if (!dbRoleIds.contains(roleId)) {
                EmployeeRoleDO rel = new EmployeeRoleDO();
                rel.setEmployeeId(empId);
                rel.setRoleId(roleId);
                rel.setIsDeleted(0);
                employeeRoleMapper.insert(rel);
            }
        }
    }

    /**
     * 删除指定员工(后台账号权限管理-员工管理)
     * @param employeeId
     */
    @Override
    @OperateLog(dataType = "员工", operateType = 2, description = "删除指定员工")
    public void delete(Long employeeId) {
        int row = employeeMapper.deleteById(employeeId);
        if (row > 0) {
            employeeRoleMapper
                    .delete(new LambdaQueryWrapper<EmployeeRoleDO>().eq(EmployeeRoleDO::getEmployeeId, employeeId));
        }

    }

    /**
     * 删除指定员工的角色(后台账号权限管理-员工管理)
     * @param employeeId
     * @param roleId
     * @return
     */
    @Override
    @OperateLog(dataType = "员工", operateType = 2, description = "删除指定员工的角色")
    public DeleteEmployeeRoleOperateDTO deleteRole(Long employeeId, Long roleId) {

        LambdaQueryWrapper<EmployeeRoleDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId)
                .eq(EmployeeRoleDO::getRoleId, roleId);
        employeeRoleMapper.delete(wrapper);

        DeleteEmployeeRoleOperateDTO dto = new DeleteEmployeeRoleOperateDTO();
        dto.setEmployeeId(employeeId);
        dto.setRoleId(String.valueOf(roleId));
        return dto;

    }

    /**
     * 更新员工登录信息
     * @param employeeId
     * @param ip
     * @param time
     */
    @Override
    @OperateLog(dataType = "员工", operateType = 4, description = "更新员工登录信息")
    public void updateLoginInfo(Long employeeId, String ip, LocalDateTime time) {

        EmployeeDO employeeDO = new EmployeeDO();
        employeeDO.setId(employeeId);
        employeeDO.setLastLoginIp(ip);
        employeeDO.setLastLoginTime(time);

        employeeMapper.updateById(employeeDO);
    }

    @Override
    public Set<String> getPermissionAlias(Long employeeId) {
        return null;
    }

    @Override
    public boolean saveBatch(Collection<EmployeeDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<EmployeeDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean updateBatchById(Collection<EmployeeDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(EmployeeDO entity) {
        return false;
    }

    @Override
    public EmployeeDO getOne(Wrapper<EmployeeDO> queryWrapper, boolean throwEx) {
        return null;
    }

    @Override
    public Optional<EmployeeDO> getOneOpt(Wrapper<EmployeeDO> queryWrapper, boolean throwEx) {
        return Optional.empty();
    }

    @Override
    public Map<String, Object> getMap(Wrapper<EmployeeDO> queryWrapper) {
        return null;
    }

    @Override
    public <V> V getObj(Wrapper<EmployeeDO> queryWrapper, Function<? super Object, V> mapper) {
        return null;
    }

    @Override
    public BaseMapper<EmployeeDO> getBaseMapper() {
        return null;
    }

    @Override
    public Class<EmployeeDO> getEntityClass() {
        return null;
    }
}
